package com.sweet.mealon.face.daily.lock.clh;

import lombok.val;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * @author: crazier.huang
 * @project: faceDaily
 * @date: 2021/4/29 星期四
 * @desc:
 */
public class CLHLock {
    public static class CLHNode{
        private volatile boolean isLocked = true;
    }

    @SuppressWarnings("unused")
    private volatile CLHNode tail;

    private static final ThreadLocal<CLHNode> nodeLocal = new ThreadLocal<CLHNode>();

    /**
     * 构建一个CLHLock对象中变量名为tail，类型为CLHNode的原子更新器（该变量必须有volatile关键字修饰）
     */
    private static final AtomicReferenceFieldUpdater<CLHLock,CLHNode> updater = AtomicReferenceFieldUpdater.newUpdater(
            CLHLock.class,CLHNode.class,"tail");

    public void lock(){
        CLHNode node = new CLHNode();
        nodeLocal.set(node);
        CLHNode preNode = updater.getAndSet(this,node);
        if(preNode != null){
            int count = 0;
            while (preNode.isLocked){
                count++;
            }
            System.out.println(String.format("lock times - %s",count));
        }
    }

    public void unlock(){
        CLHNode node = nodeLocal.get();
        if(updater.compareAndSet(this,node,null)){
            node.isLocked=false;
        }
    }

    @Test
    public void  testCLHLock() throws InterruptedException {
        Student st = new Student(new CLHLock());
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(new CLHLockThread(st));
            t.start();
        }
        TimeUnit.SECONDS.sleep(30);
    }
}
